#include "qvaluexml.h"



#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QSize>
#include <QRect>
#include <QDateTime>
#include <QLineEdit>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QDateTimeEdit>
#include <QComboBox>

using namespace SHAREDLIB;


QVariant XMLValue::value()
{
    if(m_value.isValid())
    {
        return m_value;
    }
    else
    {
        return defaultValue();
    }
}

QVariant XMLValue::defaultValue()
{
    return "";
}

void XMLValue::setValue(QVariant value)
{
    m_value=value;
}

QString XMLValue::valueText()
{
    return m_value.toString();
}

void XMLValue::setType(const QString &type)
{
    m_type=type;
}

void XMLValue::write(QXmlStreamWriter *w)
{
    w->writeStartElement("",m_type);
    writeValue(w);
    w->writeEndElement();
}

void XMLValue::writeValue(QXmlStreamWriter *w)
{
    w->writeCharacters(m_value.toString());
}

QString XMLValue::readSubValue(QXmlStreamReader *r)
{
    QString ret;
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
            break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            ret=r->text().toString();
            break;
        default:
            break;
        }
    }
    return ret;
}

void XMLStringValue::read(QXmlStreamReader *r)
{
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
            break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            m_value=r->text().toString();
            break;
        default:
            break;
        }
    }
}

void XMLStringValue::writeValue(QXmlStreamWriter *w)
{
    w->writeCharacters(m_value.toString());
}

QWidget* XMLStringValue::valueEditor()
{
    return new QLineEdit;
}

QVariant XMLStringValue::defaultValue()
{
    return "";
}

void XMLIntValue::read(QXmlStreamReader *r)
{
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
             break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            m_value=r->text().toString().toInt();
            break;
        default:
            break;
        }
    }
}

void XMLIntValue::writeValue(QXmlStreamWriter *w)
{
    w->writeStartElement("","number");
    w->writeCharacters(QString::number(m_value.toInt()));
    w->writeEndElement();
}

QWidget* XMLIntValue::valueEditor()
{
    QSpinBox *b=new QSpinBox;
    b->setRange(0xfffffffe,0x7fffffff);
    return b;
}

QString XMLIntValue::valueText()
{
    return value().toString();
}

QVariant XMLIntValue::defaultValue()
{
    return 0;
}

void XMLFloatValue::read(QXmlStreamReader *r)
{
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
             break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            m_value=r->text().toString().toDouble();
            break;
        default:
            break;
        }
    }
}

void XMLFloatValue::writeValue(QXmlStreamWriter *w)
{
    w->writeStartElement("","float");
    w->writeCharacters(QString::number(m_value.toDouble()));
    w->writeEndElement();
}

QWidget* XMLFloatValue::valueEditor()
{
    QDoubleSpinBox *d=new QDoubleSpinBox;
    d->setRange(0xfffffffe,0x7fffffff);
    return d;
}

QString XMLFloatValue::valueText()
{
    return value().toString();
}

QVariant XMLFloatValue::defaultValue()
{
    return 0.00;
}

void XMLBoolValue::read(QXmlStreamReader *r)
{
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
             break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            m_value=r->text().toString()=="true";
            break;
        default:
            break;
        }
    }
}

void XMLBoolValue::writeValue(QXmlStreamWriter *w)
{
    w->writeStartElement("","bool");
    w->writeCharacters(m_value.toBool()?"true":"false");
    w->writeEndElement();
}

QWidget* XMLBoolValue::valueEditor()
{
    QComboBox *b=new QComboBox;
    b->addItems(QStringList()<<"true"<<"false");
    return b;
}

QString XMLBoolValue::valueText()
{
    return value().toString();
}

QVariant XMLBoolValue::defaultValue()
{
    return true;
}

void XMLTimeValue::read(QXmlStreamReader *r)
{
    QTime ti;
    int h,m,s;
    h=m=s=0;
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
        {
            const QString name=r->name().toString();
            if(name=="hour")
            {
                h=readSubValue(r).toInt();
            }
            else if(name=="minute")
            {
                m=readSubValue(r).toInt();
            }
            else if(name=="second")
            {
                s=readSubValue(r).toInt();
            }
        }
             break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            break;
        default:
            break;
        }
    }
    ti.setHMS(h,m,s);
    m_value=ti;
}

void XMLTimeValue::writeValue(QXmlStreamWriter *w)
{
    QTime ti=m_value.toTime();
    w->writeStartElement("","time");

    w->writeStartElement("hour");
    w->writeCharacters(QString::number(ti.hour()));
    w->writeEndElement();

    w->writeStartElement("minute");
    w->writeCharacters(QString::number(ti.minute()));
    w->writeEndElement();

    w->writeStartElement("second");
    w->writeCharacters(QString::number(ti.second()));
    w->writeEndElement();

    w->writeEndElement();
}

QString XMLTimeValue::valueText()
{
    QTime ti=value().toTime();
    return QString("%1:%2:%3").arg(ti.hour()).arg(ti.minute()).arg(ti.second());
}

QWidget* XMLTimeValue::valueEditor()
{
    return new QTimeEdit;
}

QVariant XMLTimeValue::defaultValue()
{
    QTime ti=QTime(0,0,0);
    return QVariant(ti);
}

void XMLDateValue::read(QXmlStreamReader *r)
{
    QDate dt;
    int y,m,d;
    y=m=d=0;
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
        {
            const QString name=r->name().toString();
            if(name=="year")
            {
                y=readSubValue(r).toInt();
            }
            else if(name=="month")
            {
                m=readSubValue(r).toInt();
            }
            else if(name=="day")
            {
                d=readSubValue(r).toInt();
            }
        }
             break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            break;
        default:
            break;
        }
    }
    dt.setDate(y,m,d);
    m_value=dt;
}

void XMLDateValue::writeValue(QXmlStreamWriter *w)
{
    QDate dt=m_value.toDate();
    w->writeStartElement("","date");

    w->writeStartElement("year");
    w->writeCharacters(QString::number(dt.year()));
    w->writeEndElement();

    w->writeStartElement("month");
    w->writeCharacters(QString::number(dt.month()));
    w->writeEndElement();

    w->writeStartElement("day");
    w->writeCharacters(QString::number(dt.day()));
    w->writeEndElement();

    w->writeEndElement();
}

QString XMLDateValue::valueText()
{
    QDate dt=value().toDate();
    return QString("%1-%2-%3").arg(dt.year()).arg(dt.month()).arg(dt.day());
}

QWidget* XMLDateValue::valueEditor()
{
    return new QDateEdit;
}

QVariant XMLDateValue::defaultValue()
{
    QDate dt=QDate(2000,1,1);
    return QVariant(dt);
}

void XMLDateTimeValue::read(QXmlStreamReader *r)
{
    QDateTime dt;
    int y,m,d;
    int h,min,s;
    y=m=d=h=min=s=0;
    for(bool finished=false;!finished && !r->hasError();)
    {
        switch(r->readNext())
        {
        case QXmlStreamReader::StartElement:
        {
            const QString name=r->name().toString();
            if(name=="year")
            {
                y=readSubValue(r).toInt();
            }
            else if(name=="month")
            {
                m=readSubValue(r).toInt();
            }
            else if(name=="day")
            {
                d=readSubValue(r).toInt();
            }
            else if(name=="hour")
            {
                h=readSubValue(r).toInt();
            }
            else if(name=="minute")
            {
                min=readSubValue(r).toInt();
            }
            else if(name=="second")
            {
                s=readSubValue(r).toInt();
            }
        }
             break;
        case QXmlStreamReader::EndElement:
            finished=true;
            break;
        case QXmlStreamReader::Characters:
            break;
        default:
            break;
        }
    }
    dt.setDate(QDate(y,m,d));
    dt.setTime(QTime(h,min,s));
    m_value=dt;
}

void XMLDateTimeValue::writeValue(QXmlStreamWriter *w)
{
    QDateTime dt=m_value.toDateTime();
    w->writeStartElement("","datetime");

    w->writeStartElement("year");
    w->writeCharacters(QString::number(dt.date().year()));
    w->writeEndElement();

    w->writeStartElement("month");
    w->writeCharacters(QString::number(dt.date().month()));
    w->writeEndElement();

    w->writeStartElement("day");
    w->writeCharacters(QString::number(dt.date().day()));
    w->writeEndElement();

    w->writeStartElement("hour");
    w->writeCharacters(QString::number(dt.time().hour()));
    w->writeEndElement();

    w->writeStartElement("minute");
    w->writeCharacters(QString::number(dt.time().minute()));
    w->writeEndElement();

    w->writeStartElement("second");
    w->writeCharacters(QString::number(dt.time().second()));
    w->writeEndElement();

    w->writeEndElement();
}

QString XMLDateTimeValue::valueText()
{
    QDateTime dtt=value().toDateTime();
    return QString("%1-%2-%3 %4:%5:%6").arg(dtt.date().year()).arg(dtt.date().month()).arg(dtt.date().day())
            .arg(dtt.time().hour()).arg(dtt.time().minute()).arg(dtt.time().second());
}

QWidget* XMLDateTimeValue::valueEditor()
{
    return new QDateTimeEdit;
}

QVariant XMLDateTimeValue::defaultValue()
{
    QDateTime dtt=QDateTime(QDate(2000,1,1),QTime(0,0,0));
    return QVariant(dtt);
}


XMLValue* XMLValueFactory::create(const QString &type)
{
    XMLValue *xml=NULL;
    if(type=="String")
    {
        xml=new XMLStringValue;
    }
    else if(type=="Int")
    {
        xml=new XMLIntValue;
    }
    else if(type=="Float")
    {
        xml=new XMLFloatValue;
    }
    else if(type=="Bool")
    {
        xml=new XMLBoolValue;
    }
    else if(type=="Time")
    {
        xml=new XMLTimeValue;
    }
    else if(type=="Date")
    {
        xml=new XMLDateValue;
    }
    else if(type=="DateTime")
    {
        xml=new XMLDateTimeValue;
    }
    if(xml!=NULL)
    {
        xml->setType(type);
    }
    return xml;
}

QStringList XMLValueFactory::supports()
{
    QStringList list;
    list<<"String"<<"Int"<<"Float"<<"Bool"
       <<"Time"<<"Date"<<"DateTime";
    return list;
}
